// 带有变量定义和函数定义的语言
grammar Cymbol; //程序名称和.g4名称一致即可
@header {        //一种action,定义生成的词法语法解析文件的头，当使用java的时候，生成的类需要包名，可以在这里统一定义
 package com.taotao.antlr4;
}

//  一个程序由若干个语句构成，EOF 是结束符表示程序结束
prog : (varDecl | funcDecl)* EOF ;
// 变量定义
varDecl : TYPE ID ('=' expr)? ';' ;
// 函数定义
funcDecl : TYPE ID '('  formalParams ')' block ;
// 函数形参
formalParams : formalParam (',' formalParam)* ;
formalParam : TYPE ID ;

// 语句块
block : '{' stat* '}' ;

// 语句
stat : block
       | varDecl
       | 'if'  expr 'then' stat ('else' stat)?
       | 'return' expr? ';'
       | expr '=' expr ';'
       | expr ';'
        ;

// 表达式
expr :  ID '(' exprList? ')' ';'
        | expr '[' expr ']' ';'
        | '-' expr
        | '!' expr
        | expr '^' expr
        | expr ('*' | '/') expr
        | expr ('+' | '-') expr
        | expr ('==' | '!=') expr
        | '(' expr ')'
        | ID
        | INT
        ;

exprList : expr (',' expr)*;


TYPE : 'int' | 'double' | 'void';

// 标识符：仅能由下划线或字母开头且由下划线字母或数字组成
ID : ('_' | LETTER) WORD*;
// 整数
INT : '0' | ('+' | '-')? [1-9]NUMBER* ;
// 浮点数
FLOAT : INT '.' NUMBER+  ;






// 文档注释  antlr 有最前规则优先匹配的原则，所以 文档注释要写在多行注释前面
DOC_COMMENT : '/**' (~'\n')* '*/'  -> skip ;
// 单行注释定义   (~'\n')* 表示非换行符的任意字符
SL_COMMENT : '//' (~'\n')* '\n'  -> skip ;
// 多行注释
ML_COMMENT : '/*' (~'\n')* '*/'  -> skip ;


//4个空白字符  ->skip表示antlr4在分析语言的文本时，符合这个规则的词法将被无视
WS : [ \t\n\r]+ -> skip ;


// 语法片段 可以作为替换词法中相同的部分
fragment LETTER : [a-zA-Z];
fragment NUMBER : [0-9];
fragment WORD : '_' | LETTER | NUMBER;


